using System;
using System.Collections;
using System.Collections.Generic;
using CS;
using Unity.XR.CoreUtils;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.XR.Interaction.Toolkit;
using UnityEngine.XR.Interaction.Toolkit.Interactors;
using UnityEngine.XR.Interaction.Toolkit.Samples.StarterAssets;

public class PlayerManager : MonoBehaviour
{
    private const float StopSpeed = 0;
    private const float WalkSpeed = 2.5f;


    [Header("左右手柄Trigger键")] public InputActionProperty mLeftTriggerAction;
    public InputActionProperty mRightTriggerAction;

    private CharacterController mCC;
    private DynamicMoveProvider mMoveProvider;

    public static PlayerManager Instance;
    private NearFarInteractor mLeftNearFarInteractor;
    private NearFarInteractor mRigNearFarInteractor;

    private GameObject mLeftHoveredGO;
    private GameObject mRightHoveredGo;

    private TriggerEnterWrap mEnterWarp;
    private TriggerExitWrap mExitWrap;

    private XROrigin mXROrigin;

    /// <summary>
    /// XR射线和鼠标点击射线 点击事件
    /// </summary>
    public static UnityEvent<GameObject> OnRayClickEvent = new UnityEvent<GameObject>();

    /// <summary>
    /// 物理Enter触发事件
    /// </summary>
    public static UnityEvent<Collider> OnTriggerEnterEvent = new UnityEvent<Collider>();

    /// <summary>
    /// 物理Exit触发事件
    /// </summary>
    public static UnityEvent<Collider> OnTriggerExitEvent = new UnityEvent<Collider>();

    private void Awake()
    {
        Instance = this;
    }

    void Start()
    {
        mXROrigin = GetComponent<XROrigin>();
        mCC = GetComponent<CharacterController>();
        mLeftNearFarInteractor = transform.Find("Camera Offset/Left Controller/Near-Far Interactor")
            .GetComponent<NearFarInteractor>();
        mRigNearFarInteractor = transform.Find("Camera Offset/Right Controller/Near-Far Interactor")
            .GetComponent<NearFarInteractor>();
        mMoveProvider = transform.Find("Locomotion/Move").GetComponent<DynamicMoveProvider>();
        mLeftNearFarInteractor.hoverEntered.AddListener(OnLHandHoverEntered);
        mLeftNearFarInteractor.hoverExited.AddListener(OnLHandHoverExited);
        mRigNearFarInteractor.hoverEntered.AddListener(OnRHandHoverEntered);
        mRigNearFarInteractor.hoverExited.AddListener(OnRHandHoverExited);
        mEnterWarp = GetComponent<TriggerEnterWrap>();
        mExitWrap = GetComponent<TriggerExitWrap>();
        mEnterWarp.Event += OnTriggerEntered;
        mExitWrap.Event += OnTriggerExited;
    }

    private void OnDestroy()
    {
        mLeftNearFarInteractor.hoverEntered.RemoveListener(OnLHandHoverEntered);
        mLeftNearFarInteractor.hoverExited.RemoveListener(OnLHandHoverExited);
        mRigNearFarInteractor.hoverEntered.RemoveListener(OnRHandHoverEntered);
        mRigNearFarInteractor.hoverExited.RemoveListener(OnRHandHoverExited);
        mEnterWarp.Event -= OnTriggerEntered;
        mExitWrap.Event -= OnTriggerExited;
    }

    void Update()
    {
        XRAndInputRayClick();
    }

    #region Input Action Method

    private void OnRHandHoverExited(HoverExitEventArgs arg0)
    {
        if (arg0.interactableObject.transform.gameObject.layer == LayerMask.NameToLayer("Interactable"))
        {
            mRightHoveredGo = null;
        }
    }

    private void OnRHandHoverEntered(HoverEnterEventArgs arg0)
    {
        if (arg0.interactableObject.transform.gameObject.layer == LayerMask.NameToLayer("Interactable"))
        {
            mRightHoveredGo = arg0.interactableObject.transform.gameObject;
        }
    }

    private void OnLHandHoverExited(HoverExitEventArgs arg0)
    {
        if (arg0.interactableObject.transform.gameObject.layer == LayerMask.NameToLayer("Interactable"))
        {
            mLeftHoveredGO = null;
        }
    }

    private void OnLHandHoverEntered(HoverEnterEventArgs arg0)
    {
        if (arg0.interactableObject.transform.gameObject.layer == LayerMask.NameToLayer("Interactable"))
        {
            mLeftHoveredGO = arg0.interactableObject.transform.gameObject;
        }
    }

    /// <summary>
    /// XR左右手柄射线物体点击和模拟器鼠标右键点击
    /// </summary>
    private void XRAndInputRayClick()
    {
        if (Input.GetMouseButtonDown(1))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out RaycastHit hit, 10, 1 << LayerMask.NameToLayer("Interactable")))
            {
                Debug.Log($"HitName:{hit.collider.name}");
                OnRayClickEvent?.Invoke(hit.collider.gameObject);
            }
        }

        if (mLeftTriggerAction.action.WasPressedThisFrame())
        {
            if (mLeftHoveredGO != null)
            {
                Debug.Log($"LeftRayHitName:{mLeftHoveredGO.name}");
                OnRayClickEvent?.Invoke(mLeftHoveredGO);
            }
        }

        if (mRightTriggerAction.action.WasPressedThisFrame())
        {
            if (mRightHoveredGo != null)
            {
                Debug.Log($"RightRayHitName:{mRightHoveredGo.name}");
                OnRayClickEvent?.Invoke(mRightHoveredGo);
            }
        }
    }

    #endregion

    #region Trigger Method

    private void OnTriggerEntered(Collider obj)
    {
        OnTriggerEnterEvent?.Invoke(obj);
        if (obj.gameObject.name == "StartTrigger")
        {
            SetPlayerMove(false);
            SetCControlActive(false);
            VolumeControl.StartBlackScene(
                enterCallBack: () => { SetPlayerTrans(new Vector3(-8.08f, Camera.main.transform.position.y, -8.64f),new Vector3(0,90,0)); },
                exitCallBacl: () =>
                {
                    SetPlayerMove(true);
                    SetCControlActive(true);
                });
        }
    }

    private void OnTriggerExited(Collider obj)
    {
        OnTriggerExitEvent?.Invoke(obj);
    }

    #endregion

    #region Player

    /// <summary>
    /// 设置玩家位置和旋转
    /// </summary>
    public void SetPlayerTrans(Vector3 pos, Vector3 rot = default)
    {
        mXROrigin.MoveCameraToWorldLocation(pos);
        Quaternion newRotation = Quaternion.Euler(rot);
        mXROrigin.transform.rotation = newRotation;
    }


    public void SetPlayerMove(bool state)
    {
        if (mMoveProvider.enabled)
        {
            mMoveProvider.moveSpeed = state ? WalkSpeed : StopSpeed;
        }
    }

    public void SetCControlActive(bool active)
    {
        mCC.enabled = active;
    }

    #endregion
}